import base64
import datetime
import logging
from flask import Blueprint, render_template, request, jsonify
from bilibili_api import search, sync, video
from exts import db
from models import MonitoringTask, MonitoredVideo, Comment
import requests
import asyncio
from script.spider_common_method import save_video, filter_string, get_all_comment, update_comment, \
    delete_video_comments, \
    re_crawling_video_comments
from utils.CredentialUtil import CredentialConfig

task_bp = Blueprint("task", __name__, url_prefix="/task")


# 任务详情
@task_bp.route('/detail/<task_id>')
def tasks_detail(task_id):
    task = MonitoringTask.query.get(int(task_id))
    videos = []
    if task.monitored_videos is not None:
        for bvid in task.monitored_videos.split(','):
            task_video = MonitoredVideo.query.filter_by(bvid=bvid, is_banned=False).first()
            videos.append(task_video)
    return render_template('task_detail.html', task=task, videos=videos)


# 创建监控话题任务
@task_bp.route('/create_topic_tasks', methods=['POST'])
def create_topic_tasks():
    response = {}
    try:
        # 确保请求中有JSON数据
        if request.is_json:
            # 获取JSON数据
            data = request.get_json()
            # 从JSON数据中获取videos列表
            selectedVideos = data.get('videos', [])
            selectedVideosStr = ','.join(selectedVideos)
            task_name = data.get('task_name')
            task_name = filter_string(task_name)  # 视频标题
            # 创建监控话题任务对象
            task = MonitoringTask(task_name=task_name, task_type='自建话题', topic=task_name,
                                  monitored_videos=selectedVideosStr)
            # 将监控话题任务数据存储到数据库
            db.session.add(task)
            db.session.commit()
            # 存储监控视频
            for bvid in selectedVideos:
                sync(save_video(bvid))
                error_message = sync(get_all_comment(bvid))
                if error_message:
                    response['status'] = 'error'
                    response['message'] = '操作失败,保存评论失败'
                    return jsonify(response), 404
            # 响应请求
            response['status'] = 'success'
            response['message'] = '操作成功'
            return jsonify(response), 200
        else:
            # 响应请求
            response['status'] = 'error'
            response['message'] = '操作失败'
            return jsonify(response), 404
    except Exception as e:
        db.session.rollback()
        logging.error("An error occurred: %s", e)  # 使用logging记录错误
        response['status'] = 'error'
        response['message'] = '操作失败'
        return jsonify(response), 500  # 发生异常，返回500状态码表示服务器内部错误


# 创建监控视频任务
@task_bp.route('/create_video_tasks', methods=['POST'])
def create_video_tasks():
    response = {}
    try:
        # 确保请求中有JSON数据
        if request.is_json:
            # 获取JSON数据
            data = request.get_json()
            # 从JSON数据中获取videos列表
            bvid = data.get('video_bvid')
            print(bvid)

            v = video.Video(bvid=bvid, credential=CredentialConfig.get_credential())
            # 获取视频信息
            info = asyncio.run(v.get_info())
            task_name = filter_string(info['title'])  # 视频标题
            # 创建监控话题任务对象
            task = MonitoringTask(task_name=task_name, task_type='自建视频', topic=task_name, monitored_videos=bvid)
            # 将监控话题任务数据存储到数据库
            db.session.add(task)
            db.session.commit()
            # 存储监控视频
            asyncio.run(save_video(bvid))
            # 响应请求
            response['status'] = 'success'
            response['message'] = '操作成功'
            return jsonify(response), 200
        else:
            # 响应请求
            response['status'] = 'error'
            response['message'] = '操作失败'
            return jsonify(response), 404
    except Exception as e:
        db.session.rollback()
        logging.error("An error occurred: %s", str(e))  # 使用logging记录错误
        response['status'] = 'error'
        response['message'] = str(e)
        return jsonify(response), 500  # 发生异常，返回500状态码表示服务器内部错误


# 激活任务
@task_bp.route('/active_tasks/<monitor_id>')
async def active_monitor_task(monitor_id):
    response = {}
    try:
        # 从数据库中获取指定的监控任务
        monitor_task = MonitoringTask.query.get(monitor_id)
        # 如果监控任务不存在，返回错误信息
        if monitor_task is None:
            response['status'] = 'error'
            response['message'] = '监控任务不存在'
            return jsonify(response), 404

        # 更新监控任务的激活状态
        monitor_task.is_active = True
        tasks = []
        # 根据是否是第一次激活，选择爬取全部评论或增量评论的函数
        for monitor_video_bvid in monitor_task.monitored_videos.split(','):
            task_func = get_all_comment if monitor_task.end_time is None else update_comment
            # 将任务添加到任务列表中
            tasks.append(task_func(monitor_video_bvid))

        # 使用asyncio.gather并发执行所有任务，并处理可能的异常
        results = await asyncio.gather(*tasks, return_exceptions=True)
        for result in results:
            # 如果任务执行过程中产生了异常
            if isinstance(result, Exception):
                db.session.rollback()  # 回滚数据库的更改
                response['status'] = 'error'
                response['message'] = str(result)
                return jsonify(response), 500

        # 如果所有任务都成功执行，提交数据库的更改
        db.session.commit()
        response['status'] = 'success'
        response['message'] = '操作成功'
    except Exception as e:
        # 如果在处理过程中出现了未预料的异常
        db.session.rollback()  # 回滚数据库的更改
        response['status'] = 'error'
        response['message'] = '操作失败'
        return jsonify(response), 500

    # 返回成功的响应
    return jsonify(response), 200


# 停止任务
@task_bp.route('/stop_tasks/<monitor_id>')
def stop_monitor_task(monitor_id):
    response = {}
    try:
        monitor_task = MonitoringTask.query.get(monitor_id)
        if monitor_task is None:
            response['status'] = 'error'
            response['message'] = '监控任务不存在'
            return jsonify(response), 404  # 返回404状态码表示未找到资源

        monitor_task.is_active = False
        monitor_task.end_time = datetime.datetime.now()
        db.session.commit()
        response['status'] = 'success'
        response['message'] = '操作成功'
        return jsonify(response), 200  # 操作成功，返回200状态码
    except Exception as e:
        logging.error("An error occurred: %s", e)  # 使用logging记录错误
        response['status'] = 'error'
        response['message'] = '操作失败'
        return jsonify(response), 500  # 发生异常，返回500状态码表示服务器内部错误


# 删除任务
@task_bp.route('/delete_tasks/<monitor_id>')
def delete_monitor_task(monitor_id):
    response = {}
    try:
        monitor_task = MonitoringTask.query.get(monitor_id)
        if monitor_task is None:
            response['status'] = 'error'
            response['message'] = '监控任务不存在'
            return jsonify(response), 404  # 返回404状态码表示未找到资源
        for bvid in monitor_task.monitored_videos.split(','):
            # 删除视频
            MonitoredVideo.query.filter_by(bvid=bvid).delete()
            # 删除评论
            success, message = delete_video_comments(bvid)
            if not success:
                raise Exception(message)
        db.session.delete(monitor_task)
        db.session.commit()
        response['status'] = 'success'
        response['message'] = '操作成功'
        return jsonify(response), 200  # 操作成功，返回200状态码
    except Exception as e:
        db.session.rollback()
        logging.error("An error occurred: %s", e)  # 使用logging记录错误
        response['status'] = 'error'
        response['message'] = '操作失败'
        return jsonify(response), 500  # 发生异常，返回500状态码表示服务器内部错误


# 重新爬取任务的所有评论
@task_bp.route('/restart_task/<monitor_id>')
async def re_crawling_task_comments(monitor_id):
    response = {}
    try:
        monitor_task = MonitoringTask.query.get(monitor_id)
        if monitor_task:
            for bvid in monitor_task.monitored_videos.split(','):
                success, message = await re_crawling_video_comments(bvid)
                if not success:
                    raise Exception(message)  # 如果有错误，抛出异常
            response['status'] = 'success'
            response['message'] = '操作成功'
            return jsonify(response), 200  # 操作成功
        else:
            response['status'] = 'error'
            response['message'] = '未找到监控任务'
            return jsonify(response), 404  # 表示未找到资源
    except Exception as e:
        logging.error("An error occurred: %s", e)  # 使用logging记录错误
        response['status'] = 'error'
        response['message'] = '操作失败'
        return jsonify(response), 500  # 表示内部错误
